package edu.gxmzu.task.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import edu.gxmzu.task.entity.Attachments;
import edu.gxmzu.task.entity.Message;
import edu.gxmzu.task.entity.MessageEntity;
import edu.gxmzu.task.entity.TaskDistributeEntity;
import edu.gxmzu.task.mapper.AttachmentsMapper;
import edu.gxmzu.task.mapper.MessageMapper;
import edu.gxmzu.task.mapper.MessageMapper1;
import edu.gxmzu.task.mapper.TaskDisposeMapper;
import edu.gxmzu.task.service.TaskDisposeService;
import edu.gxmzu.task.utils.FileHashUtil;
import edu.gxmzu.task.utils.FileUtil;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.*;

/**
 * author: lrf
 * time: 2024-11-29
 * version : V1
 */
///最大文件大小为11m
@Service

@Slf4j
public class TaskDisposeServiceImpl implements TaskDisposeService {
    private static final Logger logger = LoggerFactory.getLogger(TaskDisposeServiceImpl.class);
    @Autowired
    private TaskDisposeMapper taskDisposeMapper;

    @Autowired
    private AttachmentsMapper attachmentsMapper;

    @Autowired
    private MessageMapper1 messageMapper1;

    @Override
    public List<Map<String, Object>> getUserName(String name) {
        return taskDisposeMapper.getUserName(name);
    }

    @Override
    public int taskDistribute(TaskDistributeEntity distribute) {
//        logger.info("distribute===>id" + distribute.getUserId());

        int insert = taskDisposeMapper.insert(distribute);
        MessageEntity message = new MessageEntity();
        message.setUserId(distribute.getUserId());
        message.setAppointorId(distribute.getAppointorId());
        message.setWorkeId(distribute.getId());
        message.setStatusId(0);
        int i = messageMapper1.insert(message);
        return insert;

    }

    @Override
    public Map<String, Object> uploadFile(MultipartFile file) throws IOException {
        Attachments attachments = new Attachments();
        Map<String, Object> result = new HashMap<>();
        try {
            String originalFileName = null;
            if(file != null){
                originalFileName = file.getOriginalFilename();
            }

            String algorithm = "SHA-256";       // 文件编码
            if (originalFileName == null || originalFileName.isEmpty()) {
                result.put("message", "File name is empty");
                return result;
            }
            // 文件名
            String fileName = FileUtil.getFileName(originalFileName);
            // 文件类型
            String extension = FileUtil.getFileExtension(originalFileName);

            // 文件大小
            long size = file.getSize();

            // 获取项目路径并构建文件保存路径
            String projectPath = System.getProperty("user.dir");
            String filesPath = projectPath + File.separator + "WEB-INF" + File.separator + "files";
            File directory = new File(filesPath);

            // 确保目标文件夹存在
            if (!directory.exists()) {
                directory.mkdirs();
            }

            // 设置文件保存路径
            String filesRealPath = filesPath + File.separator + originalFileName;
            File saveFile = new File(filesRealPath);
            String newFileName = null;

            // 如果文件已存在，生成新的文件名
            if (saveFile.exists()) {
                newFileName = System.currentTimeMillis() + "_" + fileName + "." + extension;
                saveFile = new File(filesPath + File.separator + newFileName);
            }

            logger.info("Saving file to: " + saveFile.getAbsolutePath());
            file.transferTo(saveFile);

            // 获取文件哈希值
            String fileHash = FileHashUtil.getFileHash(saveFile.getAbsolutePath(), algorithm);

            // 插入数据库
            attachments.setName(newFileName != null ? newFileName : originalFileName);
            attachments.setHash(fileHash);
            attachments.setType(extension);
            attachments.setSize(size);
            attachments.setPath(saveFile.getAbsolutePath());

            int insert = attachmentsMapper.insert(attachments);
            String id = attachments.getId();

            if (insert > 0){
                result.put("id", id);
            } else {
                result.put("message", "Failed to insert file record into database");
            }
        } catch (IOException | NoSuchAlgorithmException e) {
            logger.error("File upload failed", e);
            result.put("message", "File upload failed due to server error");
        }
        return result;
    }


    @Override
    public String uploadFile1(MultipartFile file) throws IOException {



        String originalFilename1 = file.getOriginalFilename();  //abc.jpg
        //截取原始文件名的后缀（使用UUID+原始文件名的后缀以防上传文件名重复）
        String suffix = originalFilename1.substring(originalFilename1.lastIndexOf("."));  // suffix = .jpg  截取是带点的后缀

        // 使用UUID重新生成文件名,防止文件名重复,造成后面上传的文件覆盖前面上传的文件
        String originalFileName = UUID.randomUUID().toString()+suffix; //随机生成的30多位+后缀
        log.info("文件名"+originalFileName);


        String algorithm = "SHA-256";       // 文件编码

        // 文件名
        String fileName = FileUtil.getFileName(originalFileName);

        // 文件类型
        String extension = FileUtil.getFileExtension(originalFileName);

        // 文件大小
        long size = file.getSize();

        String projectPath = System.getProperty("user.dir");
        String filesPath = projectPath + File.separator + "WEB-INF" + File.separator + "files";
        String filesRealPath = filesPath + File.separator + originalFileName;

        File saveFile = new File(filesRealPath);
        String newFileName = null;
        try {
            if (!saveFile.getParentFile().exists()) {
                saveFile.getParentFile().mkdirs();
            }
            file.transferTo(saveFile);
            if (saveFile.exists()) {
                // Create a unique filename
                newFileName = System.currentTimeMillis() + "_" + fileName + "." + extension;
                saveFile = new File(filesPath + File.separator + newFileName);
            }

            // 文件哈希值
            String fileHash = FileHashUtil.getFileHash(filesRealPath, algorithm);



        } catch (IOException | NoSuchAlgorithmException e) {
            logger.error("FileUploadController====>>>>upload====>>>Failed to upload file", e);
        }
        return originalFileName;
    }


    @Override
    public String getAttachmentsId() {
        return taskDisposeMapper.getAttachmentsId();
    }

    @Override
    public Map<String, Integer> countTaskNum(Long createTime, Long endTime, String title) {
        // 用于存储按天统计的任务数量
        Map<String, Integer> taskCountByDay = new HashMap<>();

        // 获取任务数据
        QueryWrapper<TaskDistributeEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.ge("create_time", createTime).le("end_time", endTime); // 时间范围条件

        // 如果传递了 title，进行模糊查询
        if (title != null && !title.isEmpty()) {
            queryWrapper.like("title", title);  // 使用 like 进行模糊查询
        }

        List<TaskDistributeEntity> taskDistributeEntities = taskDisposeMapper.selectList(queryWrapper);

        // 先统计每一天的任务数量
        Map<Integer, Integer> dayTaskCount = new HashMap<>();

        for (TaskDistributeEntity work : taskDistributeEntities) {
            long createTimestamp = Long.parseLong(work.getCreateTime()); // 获取任务的创建时间戳
            int dayIndex = getDayIndex(createTimestamp, createTime); // 根据时间戳计算是哪一天
            // 累加当天的任务数量
            dayTaskCount.put(dayIndex, dayTaskCount.getOrDefault(dayIndex, 0) + 1);
        }

        // 最后将统计的结果存入 taskCountByDay
        for (Map.Entry<Integer, Integer> entry : dayTaskCount.entrySet()) {
            taskCountByDay.put("day" + entry.getKey(), entry.getValue());
        }

        return taskCountByDay;
    }

    @Override
    public Map<String, Object> countWorkStatus(Long createTime, Long endTime, String title) {
        // 用于存储按天统计的任务数量
        Map<String, Object> result = new HashMap<>();
        Map<String, Integer> doneTaskCountByDay = new HashMap<>();
        Map<String, Integer> pendingTaskCountByDay = new HashMap<>();

        // 获取任务数据
        QueryWrapper<TaskDistributeEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.ge("create_time", createTime).le("end_time", endTime); // 时间范围条件

        // 如果传递了 title，进行模糊查询
        if (title != null && !title.isEmpty()) {
            queryWrapper.like("title", title);  // 使用 like 进行模糊查询
        }

        // 增加查询已办和代办任务的条件，使用 work_status_id = 0 和 work_status_id = 1
        queryWrapper.in("work_status_id", Arrays.asList(0, 1)); // 筛选工作状态为 0 或 1 的任务

        List<TaskDistributeEntity> taskDistributeEntities = taskDisposeMapper.selectList(queryWrapper);

        // 统计已办和待办任务数量
        Map<Integer, Integer> doneTaskCount = new HashMap<>();
        Map<Integer, Integer> pendingTaskCount = new HashMap<>();

        for (TaskDistributeEntity work : taskDistributeEntities) {
            long createTimestamp = Long.parseLong(work.getCreateTime()); // 获取任务的创建时间戳
            int dayIndex = getDayIndex(createTimestamp, createTime); // 根据时间戳计算是哪一天

            // 根据 work_status_id 判断任务是已办还是待办
            if (work.getWorkStatusId().equals(1)) { // 已办
                doneTaskCount.put(dayIndex, doneTaskCount.getOrDefault(dayIndex, 0) + 1);
            } else if (work.getWorkStatusId().equals(0)) { // 待办
                pendingTaskCount.put(dayIndex, pendingTaskCount.getOrDefault(dayIndex, 0) + 1);
            }
        }

        // 将统计结果填充到对应的 map 中
        for (Map.Entry<Integer, Integer> entry : doneTaskCount.entrySet()) {
            doneTaskCountByDay.put("day" + entry.getKey(), entry.getValue());
        }

        for (Map.Entry<Integer, Integer> entry : pendingTaskCount.entrySet()) {
            pendingTaskCountByDay.put("day" + entry.getKey(), entry.getValue());
        }

        // 将已办和待办任务的统计结果合并到 final result 中
        result.put("status_id0", pendingTaskCountByDay); // status_id0 为待办任务的统计
        result.put("status_id1", doneTaskCountByDay);    // status_id1 为已办任务的统计

        // 最终返回包含任务统计数据的 result1 map
        Map<String, Object> result1 = new HashMap<>();
        result1.put("histogram", result);

        return result1;
    }



    // 计算任务是第几天
    private int getDayIndex(long taskTimestamp, long startTimestamp) {
        // 计算任务的时间戳和开始时间戳的差值（以天为单位）
        long diff = taskTimestamp - startTimestamp;
        return (int) (diff / (1000 * 60 * 60 * 24)) + 1; // 转换为天数，+1 确保第1天从 1 开始
    }


    @Override
    public int tasksList(String userid) {
        return taskDisposeMapper.tasksList(userid);
    }

    @Override
    public int tasksGuoQiList(String userid, Long newDate) {
        return taskDisposeMapper.tasksGuoQiList(userid, newDate);
    }

    @Override
    public Object download(String name, HttpServletResponse response){
        try {
            String projectPath = System.getProperty("user.dir");
            String filesPath = projectPath + File.separator + "WEB-INF" + File.separator + "files";

            //输入流,通过输入流读取文件内容
            FileInputStream fileInputStream = new FileInputStream(new File(filesPath+name));

            //输出流,通过输出流将文件写回浏览器,在浏览器展示图片
            ServletOutputStream outputStream = response.getOutputStream();

            //设置一下为图片文件
            response.setContentType("image/jpeg");

            // 输入流读取到 内容放到 bytes数组中
            int len = 0;
            byte[] bytes = new byte[1024];
            while ((len = fileInputStream.read(bytes)) != -1){   //当为-1的时候输入流读取完成
                outputStream.write(bytes,0,len);          //写输入流到浏览器
                outputStream.flush();
            }

            //关闭资源
            outputStream.close();
            fileInputStream.close();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return null;
    }


}
